package net.aiion.weave.impl.ui.binder;

import net.aiion.weave.spi.injection.InjectionContext;
import net.aiion.weave.spi.injection.annotations.Inject;
import net.aiion.weave.spi.injection.annotations.Injects;
import net.aiion.weave.spi.naming.Context;
import net.aiion.weave.spi.naming.annotations.Named;
import net.aiion.weave.spi.naming.annotations.NotScoped;
import net.aiion.weave.spi.painters.PaintBrush;
import net.aiion.weave.spi.painters.PaintContext;
import net.aiion.weave.spi.painters.PainterService;
import net.aiion.weave.spi.painters.annotations.Paints;
import net.aiion.weave.spi.ui.Bindable;
import net.aiion.weave.spi.ui.annotations.Bind;

@NotScoped
@Named
public class Binder
{
    @Inject
    private PainterService painterService;

    @Inject
    private Context context;

    public Binder() {
    }

    @Injects(Bind.class)
    public Object injectBinding(final InjectionContext aInjectorContext) {
        final String bindableId = String.format("%s/%s", aInjectorContext.getInjectable().getClass().getName(),
            aInjectorContext.getTargetAnnotation(Bind.class).value());

        Object bindable = lookupBindable(bindableId);
        if (bindable == null) {
            bindable = aInjectorContext.forwardInjection();
            context.bind(bindableId, bindable);
        }

        return bindable;
    }

    private Bindable lookupBindable(final String aBindableId) {
        return (Bindable) context.lookup(aBindableId);
    }

    @Paints(Object.class)
    public PaintBrush paintComponent(final PaintContext aPainterContext) {
        final Bindable bindable = (Bindable) context.lookup(String.format("%s/", aPainterContext.getComponent()
            .getClass().getName()));
        if (bindable == null) {
            return aPainterContext.forwardPaint();
        }

        return painterService.paintComponent(bindable);
    }
}
